package org.aliwo.syn;

/**
 * @author xuyayuan
 * @data 2021年06月19日
 */
public class TicketThread02 {
    public static void main(String[] args) {
        SaleTicketRunnable02 saleTicketRunnable02 = new SaleTicketRunnable02();
        Thread thread1 = new Thread(saleTicketRunnable02);
        Thread thread2 = new Thread(saleTicketRunnable02);
        Thread thread3 = new Thread(saleTicketRunnable02);
        // 通过实现Runnable接口，会出现超卖的现象
        thread1.start(); // 启动售票线程
        thread2.start(); // 启动售票线程
        thread3.start(); // 启动售票线程
    }
}

class SaleTicketRunnable02 implements Runnable {
    private int ticketNum = 100; // 多个线程共享该票数变量
    private boolean loop = true;

    // private  /*synchronized*/ void sellTicket() {} 就是一个同步方法 ,同步方法如果没有使用static修饰，默认锁对象为this
    // 这个时候锁在this对象
    // 也可以在代码块上加 synchronized，同步代码块，互斥锁还是this对象
    private  /*synchronized*/ void sellTicket() { // 同步方法，同一时刻，只能有一个线程执行sellTicket()方法
        synchronized (this) { //  也可以在代码块上加 synchronized，同步代码块，互斥锁还是this对象
            if (ticketNum <= 0) {
                System.out.println("售票结束 !!!");
                loop = false;
                return;
            }

            try {
                Thread.sleep(50);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            System.out.println("窗口号 : " + Thread.currentThread().getName() + "卖出了一张票  "
                    + " 剩余票数 = : " + (--ticketNum));
        }
    }

    // 同步方法(静态的)的锁为当前类本身 , 如果方法使用static修饰，默认锁对象为当前类.class
    // private  synchronized static void sellTicket03() {} 锁是加在SaleTicketRunnable02.class
   /* private  synchronized static void sellTicket03() {

    }*/

    // private  static void sellTicket02() {}  静态方法也可以在代码块上加 synchronized，同步代码块，锁对象为当前类.class(SaleTicketRunnable02
    // .class), 如果方法使用static修饰，默认锁对象为当前类.class
   /*
    private  static void sellTicket02() {
        synchronized (SaleTicketRunnable02.class) { //  静态方法也可以在代码块上加 synchronized，同步代码块，锁对象为当前类.class
        (SaleTicketRunnable02.class)
        }
    }
    */

    @Override
    public void run() {
        while (loop) {
            sellTicket(); // sellTicket是一个同步方法
        }
    }


}

